package com.party.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.party.common.base.ApiResult;
import com.party.common.entity.MyPage;
import com.party.common.utils.PageUtil;
import com.party.entity.*;
import com.party.entity.dto.*;
import com.party.entity.vo.ExportResourceVo;
import com.party.entity.vo.SelectDeviceVo;
import com.party.entity.vo.SelectUserVo;
import com.party.mapper.PbUserMapper;
import com.party.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.party.util.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 客户信息表 服务实现类
 * </p>
 *
 * @author ccl
 * @since 2024-10-25
 */
@Slf4j
@Service
public class PbUserServiceImpl extends ServiceImpl<PbUserMapper, PbUser> implements PbUserService {

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private PbDeviceService pbDeviceService;

    @Resource
    private PbResourceService pbResourceService;

    @Resource
    private PbUserDeviceService pbUserDeviceService;

    @Resource
    private PbUserResourceService pbUserResourceService;

    @Resource
    private PbUserResourceHistoryService pbUserResourceHistoryService;

    @Resource
    private PbStationDeviceService pbStationDeviceService;

    @Resource
    private PbBannerService pbBannerService;

    @Resource
    private JwtTokenUtil jwtTokenUtil;

    @Resource
    private PbResourceDeviceService pbResourceDeviceService;

    @Override
    public ApiResult login(ReqLoginDto loginReqDao) {
        String loginId = loginReqDao.getLoginId();
        String password = loginReqDao.getPassword();
        //校验登陆账号不为空
        if (StringUtils.isEmpty(loginId)) {
            return ApiResult.failed(ResultCode.PARAMS_IS_NULL.getMsg());
        }
        //校验登陆密码不为空
        if (StringUtils.isEmpty(password)) {
            return ApiResult.failed(ResultCode.PARAMS_IS_NULL.getMsg());
        }

        String md5Password = MD5Util.getMd5(password).toUpperCase();
        LambdaQueryWrapper<PbUser> wrapper = new LambdaQueryWrapper();
        wrapper.eq(PbUser::getLoginId, loginId).eq(PbUser::getPassword, md5Password);
        PbUser sysUser = this.getOne(wrapper);
        if (sysUser == null) {
            throw new RuntimeException("用户不存在,请核查!");
        }
        //jwt生成token
        UserInfo userInfo = new UserInfo();
        userInfo.setLoginId(sysUser.getLoginId());
        userInfo.setUserCode(sysUser.getUserCode());
        userInfo.setUserName(sysUser.getUserName());
        userInfo.setDeptCode(sysUser.getDeptCode());
        userInfo.setMobile(sysUser.getMobile());
        userInfo.setRoleCode(sysUser.getRolesCode());
        String token = jwtTokenUtil.createToken(userInfo);
        //放入redis缓存
//        if(redisTemplate.hasKey(token)){
//            redisTemplate.delete(token);
//            redisTemplate.opsForValue().set(token,token, Integer.valueOf(MdsEnumConfig.CCP_SYSTEM_TOKEN_TIME.getCode()), TimeUnit.MINUTES);
//        }else{
//            redisTemplate.opsForValue().set(token,token, Integer.valueOf(MdsEnumConfig.CCP_SYSTEM_TOKEN_TIME.getCode()), TimeUnit.MINUTES);
//        }

        //返给前端登录人基本信息和权限
        RespLoginDto respDao = new RespLoginDto();
        respDao.setId(sysUser.getId());
        respDao.setUserCode(sysUser.getUserCode());
        respDao.setUserName(sysUser.getUserName());
        respDao.setLoginId(sysUser.getLoginId());
        respDao.setRolesCode(sysUser.getRolesCode());
        respDao.setRolesName(sysUser.getRolesName());
        respDao.setDeptCode(sysUser.getDeptCode());
        respDao.setDeptName(sysUser.getDeptName());
        respDao.setEmail(sysUser.getEmail());
        respDao.setMobile(sysUser.getMobile());
        respDao.setBirthday(sysUser.getBirthday());
        respDao.setSex(sysUser.getSex());
        respDao.setPicture(sysUser.getPicture());
        respDao.setAuthorization(token);

        return ApiResult.ok(respDao);
    }

    @Override
    public void logout(String loginId, HttpServletRequest request) {
        //String key = Base64Util.encrypt(loginId);
        String token = request.getHeader("authorization");
        if (redisTemplate.hasKey(token)) {
            redisTemplate.delete(token);
        }
    }

    @Override
    public ApiResult add(PbUser pbUser) {
        PbUser user = this.getOne(new LambdaQueryWrapper<PbUser>()
                .eq(PbUser::getLoginId, pbUser.getLoginId()));
        if (user != null) {
            return ApiResult.failed(ResultCode.USER_HAS_EXIST.getMsg());
        }

        //校验手机号码合法性
        if (StringUtils.isNotEmpty(pbUser.getMobile()) && !CheckUtils.isPhoneLegal(pbUser.getMobile())) {
            return ApiResult.failed(ResultCode.PARAMS_USER_MOBILE_LEGAL.getMsg());
        }
        //校验邮箱合法性
        if (StringUtils.isNotEmpty(pbUser.getEmail()) && !CheckUtils.isEmailLegal(pbUser.getEmail())) {
            return ApiResult.failed(ResultCode.PARAMS_USER_EMAIL_LEGAL.getMsg());
        }

        LambdaQueryWrapper<PbUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(PbUser::getUserCode);
        List<PbUser> userCodeList = this.list(wrapper);
        if (!userCodeList.isEmpty()) {
            String userCode = String.format("%06d", Integer.parseInt(userCodeList.get(0).getUserCode()) + 1);
            pbUser.setUserCode(userCode);
        }
        //String userCode = UUID.randomUUID().toString().replaceAll("-", "");
        String md5Password = MD5Util.getMd5("123456").toUpperCase();
        pbUser.setPassword(md5Password);

        pbUser.setPrOnOff(ObjectUtil.isNotEmpty(pbUser.getPrOnOff()) ? pbUser.getPrOnOff() : 1);

        pbUser.setCreateTime(new Date());
        pbUser.setUpdateTime(new Date());
        pbUser.setCreateId(MoJiCommonUtils.getUserCode());
        pbUser.setUpdateId(MoJiCommonUtils.getUserCode());
        this.save(pbUser);
        Long maxId = pbUser.getId();
        if (ObjectUtil.isNotEmpty(pbUser.getDeviceCode())) {
            List<String> ids = Arrays.asList(pbUser.getDeviceCode().split(","));
            for (String id : ids) {
                PbUserDevice pbUserDevice = new PbUserDevice();
                pbUserDevice.setUserId(maxId);
                pbUserDevice.setDeviceId(Long.valueOf(id));
                pbUserDevice.setCreateTime(new Date());
                pbUserDeviceService.save(pbUserDevice);
            }

        }
        return ApiResult.ok(true);

    }

    @Override
    public ApiResult edit(PbUser pbUser) {
        //姓名不能为空
        if (StringUtils.isEmpty(pbUser.getUserName())) {
            return ApiResult.failed(ResultCode.PARAMS_PASSWORD_IS_NULL.getMsg());
        }
        //校验手机号码合法性
        if (StringUtils.isNotEmpty(pbUser.getMobile()) && !CheckUtils.isPhoneLegal(pbUser.getMobile())) {
            return ApiResult.failed(ResultCode.PARAMS_USER_MOBILE_LEGAL.getMsg());
        }
        pbUser.setUpdateTime(new Date());
        pbUser.setUpdateId(MoJiCommonUtils.getUserCode());
        return ApiResult.ok(this.updateById(pbUser));
    }

    @Override
    public boolean delete(Long id) {
        PbUser sysUser = this.getById(id);
        if (sysUser == null) {
            throw new RuntimeException("用户不存在,请核查!");
        }
        return this.removeById(id);
    }

    @Override
    public PbUser detail(Long id) {
        PbUser sysUser = this.getById(id);
        if (sysUser == null) {
            throw new RuntimeException("用户不存在,请核查!");
        }
        return sysUser;
    }

    @Override
    public MyPage<PbUser> queryPage(QueryUserDto dto) {
        LambdaQueryWrapper<PbUser> wrapper = new LambdaQueryWrapper<>();
        if (ObjectUtil.isNotEmpty(dto.getUserName())) {
            wrapper.like(PbUser::getUserName, dto.getUserName());
        }
        if (ObjectUtil.isNotEmpty(dto.getLoginId())) {
            wrapper.like(PbUser::getLoginId, dto.getLoginId());
        }
        if (ObjectUtil.isNotEmpty(dto.getMobile())) {
            wrapper.like(PbUser::getMobile, dto.getMobile());
        }
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        wrapper.orderByDesc(PbUser::getUpdateTime);
        List<PbUser> userList = this.list(wrapper);
        if (ObjectUtil.isNotEmpty(userList)) {
            userList.forEach(user -> {
                List<PbUserDevice> pbUserDevices = pbUserDeviceService.list(
                        new LambdaQueryWrapper<PbUserDevice>()
                                .eq(PbUserDevice::getUserId, user.getId()));
                if (ObjectUtil.isNotEmpty(pbUserDevices)) {
                    List<Long> deviceIds = pbUserDevices.stream().map(PbUserDevice::getDeviceId).collect(Collectors.toList());
                    user.setDeviceIds(deviceIds);
                }

                List<PbUserResource> pbUserResources = pbUserResourceService.list(
                        new LambdaQueryWrapper<PbUserResource>()
                                .eq(PbUserResource::getUserId, user.getId()));
                if (ObjectUtil.isNotEmpty(pbUserResources)) {
                    List<Long> resourceIds = pbUserResources.stream().map(PbUserResource::getResourceId).collect(Collectors.toList());
                    user.setResourceIds(resourceIds);
                }
            });
        }
        PageInfo<PbUser> info = new PageInfo<>(userList);
        return PageUtil.PageInfo2MyPage(info);
    }

    @Override
    public boolean updateStatus(PrOnOffDto prOnOffDao) {
        PbUser sysUser = this.getById(prOnOffDao.getId());
        if (sysUser == null) {
            throw new RuntimeException("用户不存在,请核查!");
        }
        sysUser.setPrOnOff(Integer.parseInt(prOnOffDao.getPrOnOff()));

        return this.updateById(sysUser);
    }

    @Override
    public boolean resetPassword(Long id) {
        PbUser sysUser = this.getById(id);
        if (sysUser == null) {
            throw new RuntimeException("用户不存在,请核查!");
        }
        sysUser.setPassword(MD5Util.getMd5("123456").toUpperCase());
        return this.updateById(sysUser);
    }

    @Override
    public boolean modifyPassword(ModifyPasswordDto modifyPasswordDao) {
        String newPassword = modifyPasswordDao.getNewPassword();
        String oldPassword = modifyPasswordDao.getOldPassword();
        String md5NewPassword = MD5Util.getMd5(newPassword).toUpperCase();
        String md5OldPassword = MD5Util.getMd5(oldPassword).toUpperCase();
        LambdaQueryWrapper<PbUser> wrapper = new LambdaQueryWrapper();
        wrapper.eq(PbUser::getUserCode, modifyPasswordDao.getUserCode());
        PbUser sysUser = this.getOne(wrapper);
        if (sysUser == null) {
            throw new RuntimeException("用户不存在,请核查!");
        }
        if (ObjectUtil.isNotEmpty(modifyPasswordDao.getNewPassword()) && !sysUser.getPassword().equals(md5OldPassword)) {
            sysUser.setPassword(md5NewPassword);
        }
        if (ObjectUtil.isNotEmpty(modifyPasswordDao.getLoginId())) {
            sysUser.setLoginId(modifyPasswordDao.getLoginId());
        }
        if (ObjectUtil.isNotEmpty(modifyPasswordDao.getPicture())) {
            sysUser.setPicture(modifyPasswordDao.getPicture());
        }
        return this.updateById(sysUser);
    }

    @Override
    public List<SelectUserVo> userSelect() {
        List<SelectUserVo> selectUserVos = new ArrayList<>();
        List<PbUser> sysUserList = this.list();
        sysUserList.forEach(user -> {
            SelectUserVo selectUserVo = new SelectUserVo();
            BeanUtils.copyProperties(user, selectUserVo);
            selectUserVos.add(selectUserVo);
        });
        return selectUserVos;
    }

    @Override
    public boolean distribute(DistributeDto dto) {
        PbUser pbUser = this.getById(dto.getId());
        if (pbUser == null) {
            throw new RuntimeException("用户不存在,请核查!");
        }
        if (dto.getIds().isEmpty()) {
            pbUserDeviceService.remove(
                    new LambdaQueryWrapper<PbUserDevice>()
                            .in(PbUserDevice::getUserId, dto.getId()));
            return true;
        }
        List<String> list1 = Arrays.asList(dto.getIds().split(","));
        List<Long> list2 = list1.stream().map(Long::parseLong).collect(Collectors.toList());
        if (dto.getType() == 0) {//设备分配
            LambdaQueryWrapper<PbDevice> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(PbDevice::getId, list2);
            List<PbDevice> pbDevices = pbDeviceService.list(wrapper);
//            pbDevices.forEach(pbDevice->{
//                PbUserDevice pbUserDevice=pbUserDeviceService.getOne(
//                        new LambdaQueryWrapper<PbUserDevice>()
//                .eq(PbUserDevice::getDeviceId,pbDevice.getId()));
//
//                PbUser pbUser1=this.getOne(
//                        new LambdaQueryWrapper<PbUser>()
//                                .eq(PbUser::getId,pbUserDevice.getUserId()));
//                throw new RuntimeException(pbDevice.getDeviceName()+"已经分配给用户"+pbUser1.getUserName());
//            });
            List<PbUserDevice> userDevices = Lists.newArrayList();
            pbDevices.forEach(pbDevice -> {
                PbUserDevice pbUserDevice = new PbUserDevice();
                pbUserDevice.setUserId(dto.getId());
                pbUserDevice.setDeviceId(pbDevice.getId());
                pbUserDevice.setCreateTime(new Date());
                userDevices.add(pbUserDevice);

                pbDevice.setBelongUser(pbUser.getId());
            });
            pbUserDeviceService.remove(
                    new LambdaQueryWrapper<PbUserDevice>()
                            .in(PbUserDevice::getUserId, dto.getId()));
            pbUserDeviceService.saveBatch(userDevices);
            //更新设备所属用户
            pbDeviceService.updateBatchById(pbDevices);
        }
        if (dto.getType() == 1) {//资源分配
            LambdaQueryWrapper<PbResource> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(PbResource::getResourceId, list2);
            List<PbResource> pbResources = pbResourceService.list(wrapper);
            List<PbUserResource> userResources = new ArrayList<>();
            pbResources.forEach(pbResource -> {
                PbUserResource pbUserResource = new PbUserResource();
                pbUserResource.setUserId(dto.getId());
                pbUserResource.setResourceId(pbResource.getResourceId());
                pbUserResource.setCreateTime(new Date());
                userResources.add(pbUserResource);
            });
            pbUserResourceService.remove(
                    new LambdaQueryWrapper<PbUserResource>()
                            .in(PbUserResource::getUserId, dto.getId()));
            pbUserResourceService.saveBatch(userResources);
        }
        return true;
    }

    @Override
    public MyPage<PbUserResourceHistory> getResourceRecord(QueryUserDto dto) {
        LambdaQueryWrapper<PbUserResourceHistory> wrapper = new LambdaQueryWrapper<>();
        if (ObjectUtil.isNotEmpty(dto.getOpenId())) {
            wrapper.like(PbUserResourceHistory::getOpenId, dto.getOpenId());
        }
        if (ObjectUtil.isNotEmpty(dto.getResourceName())) {
            wrapper.like(PbUserResourceHistory::getResourceName, dto.getResourceName());
        }
        wrapper.orderByDesc(PbUserResourceHistory::getCreateTime);
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        List<PbUserResourceHistory> resourceHistoryList = pbUserResourceHistoryService.list(wrapper);
        for (int i = 0; i < resourceHistoryList.size(); i++) {
            resourceHistoryList.get(i).setId(resourceHistoryList.get(i).getResourceId());
        }
//        if(resourceHistoryList.size()<9){
//            if(resourceHistoryList==null){
//                resourceHistoryList=new ArrayList<>();
//            }
//            LambdaQueryWrapper<PbResource> wrapper1 = new LambdaQueryWrapper<>();
//            wrapper1.orderByDesc(PbResource::getCreateTime);
//            wrapper1.last("limit "+(9-resourceHistoryList.size()));
//            List<PbResource> resourceList=pbResourceService.list(wrapper1);
//            for(PbResource pbResource:resourceList){
//                PbUserResourceHistory pbUserResourceHistory=new PbUserResourceHistory();
//                pbUserResourceHistory.setOpenId(dto.getOpenId());
//                BeanUtils.copyProperties(pbResource,pbUserResourceHistory);
//                resourceHistoryList.add(pbUserResourceHistory);
//            }
//        }
        PageInfo<PbUserResourceHistory> info = new PageInfo<>(resourceHistoryList);
//        info.setTotal(9);
        return PageUtil.PageInfo2MyPage(info);
    }

    @Override
    public MyPage<PbDevice> getDeviceList(QueryUserDto dto) {
//        LambdaQueryWrapper<PbUser> wrapper = new LambdaQueryWrapper<>();
//        if (ObjectUtil.isNotEmpty(dto.getUserName())) {
//            wrapper.like(PbUser::getUserName, dto.getUserName());
//        }
//        if (ObjectUtil.isNotEmpty(dto.getLoginId())) {
//            wrapper.like(PbUser::getLoginId, dto.getLoginId());
//        }
//        if (ObjectUtil.isNotEmpty(dto.getMobile())) {
//            wrapper.like(PbUser::getMobile, dto.getMobile());
//        }
//        if (ObjectUtil.isNotEmpty(dto.getUserCode())) {
//            wrapper.like(PbUser::getUserCode, dto.getUserCode());
//        }
//        if (ObjectUtil.isNotEmpty(dto.getId())) {
//            wrapper.like(PbUser::getUserCode, dto.getId());
//        }
//        List<PbUser> userList = this.list(wrapper);

        LambdaQueryWrapper<PbDevice> wrapper1 = new LambdaQueryWrapper<>();
        if (ObjectUtil.isNotEmpty(dto.getId())) {
            //List<Long> ids=userList.stream().map(PbUser::getId).collect(Collectors.toList());
            wrapper1.eq(PbDevice::getBelongUser, dto.getId());
        }
        wrapper1.orderByDesc(PbDevice::getCreateTime);
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        List<PbDevice> deviceList = pbDeviceService.list(wrapper1);
        PageInfo<PbDevice> info = new PageInfo<>(deviceList);
        return PageUtil.PageInfo2MyPage(info);
    }

    @Override
    public boolean publish(PublishBannerDto dto) {
        PbBanner PbBanner1 = pbBannerService.getOne(new LambdaQueryWrapper<PbBanner>()
                .eq(PbBanner::getTitle, dto.getTitle()).eq(PbBanner::getType, dto.getType()));
        if (PbBanner1 != null) {
            throw new RuntimeException("标题已存在,请核查!");
        }
        PbUser pbUser = this.getById(dto.getUserId());
        if (pbUser == null) {
            throw new RuntimeException("当前用户不存在,请核查!");
        }
        PbBanner addBanner = new PbBanner();
        BeanUtils.copyProperties(dto, addBanner);
        addBanner.setStatus(1);//状态 0 下线 1 上线
        addBanner.setCreateTime(new Date());
        addBanner.setUpdateTime(new Date());
        addBanner.setChannel(2);
        addBanner.setOperatorId(pbUser.getUserCode());
        pbBannerService.save(addBanner);
        Long maxId = addBanner.getId();
        //设备绑定
        dto.getIds().forEach(id -> {
            PbStationDevice add = new PbStationDevice();
            add.setStationId(maxId);
            add.setDeviceId(id);
            add.setType(dto.getType());
            add.setCreateTime(new Date());
            pbStationDeviceService.save(add);
        });
        if (dto.getType() == 2) {
            List<PbBanner> list = pbBannerService.list(new LambdaQueryWrapper<PbBanner>()
                    .eq(PbBanner::getType, 2));
            if (list != null) {
                for (int i = 0; i < list.size(); i++) {
                    PbBanner pbBanner1 = list.get(i);
                    if (!pbBanner1.getId().equals(maxId) ) {
                        pbBanner1.setType(4);
                        pbBannerService.updateById(pbBanner1);
                    }
                }
            }


        }
        return true;
    }

    @Override
    public List<SelectDeviceVo> selectDevice(Long id) {
        List<SelectDeviceVo> selectDeviceVos = new ArrayList<>();
        LambdaQueryWrapper<PbDevice> wrapper = new LambdaQueryWrapper<>();
        if (ObjectUtil.isNotEmpty(id)) {
            wrapper.eq(PbDevice::getBelongUser, id);
        }
        List<PbDevice> deviceList = pbDeviceService.list(wrapper);
        if (!deviceList.isEmpty()) {
            deviceList.forEach(pbDevice -> {
                SelectDeviceVo selectDeviceVo = new SelectDeviceVo();
                BeanUtils.copyProperties(pbDevice, selectDeviceVo);
                selectDeviceVos.add(selectDeviceVo);
            });
        }
        return selectDeviceVos;
    }

    @Override
    public ApiResult importDistribute(MultipartFile file, String id) {
        try {
            List<ExportResourceVo> result = EasyExcel.read(file.getInputStream()) //调用read方法
                    //注册自定义监听器，字段校验可以在监听器内实现
                    //.registerReadListener(new UserListener())
                    .head(ExportResourceVo.class) //对应导入的实体类
                    .sheet(0) //导入数据的sheet页编号，0代表第一个sheet页，如果不填，则会导入所有sheet页的数据
                    .headRowNumber(1) //列表头行数，1代表列表头有1行，第二行开始为数据行
                    .doReadSync(); //开始读Excel，返回一个List<T>集合，继续后续入库操作
            //从excel中解析数据
            if (result == null) {
                return ApiResult.failed("导入数据为空,请核查!");
            }
            List<Long> list = result.stream().filter(t -> ObjectUtil.isNotEmpty(t.getResourceId())).map(ExportResourceVo::getResourceId).collect(Collectors.toList());
            log.info("导入的资源id={}",list);
            List<PbResourceDevice> resourceDevices = Lists.newArrayList();
            result.forEach(pbResource -> {
                    PbResourceDevice pbResourceDevice = new PbResourceDevice();
                    pbResourceDevice.setDeviceId(Long.valueOf(id));
                    pbResourceDevice.setResourceId(pbResource.getResourceId());
                    resourceDevices.add(pbResourceDevice);
            });
            pbResourceDeviceService.remove(
                    new LambdaQueryWrapper<PbResourceDevice>()
                            .eq(PbResourceDevice::getDeviceId, Long.valueOf(id))
                            .in(PbResourceDevice::getResourceId, list));
            pbResourceDeviceService.saveBatch(resourceDevices);
            return ApiResult.ok("分配成功");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("文件数据格式有误,请核查!");
        }
        //return ApiResult.ok("分配成功");
    }
}
